using System.Collections.Generic;

namespace Common.Dao
{
    /// <summary>
    /// Interface for Common Data Access Object implementation, 
    /// provide common code for data access layer such as 
    /// get, update, delete, query entities
    /// </summary>
    /// <typeparam name="TE">
    /// The target entity type that this DAO will manipulate on
    /// </typeparam>
    /// <typeparam name="TK">
    /// The target entity key type
    /// </typeparam>
    public interface ICommonDao<TE, TK>
    {
        /// <summary>
        /// Gets entity by the key.
        /// </summary>
        /// <param name="key">
        /// The specific key.
        /// </param>
        /// <returns>
        /// The matched entity.
        /// </returns>
        TE Get(TK key);

        /// <summary>
        /// Save an entity to database.
        /// </summary>
        /// <param name="inst">
        /// The entity will be saved.
        /// </param>
        /// <returns>
        /// The key of the entity.
        /// </returns>
        TK Save(TE inst);

        /// <summary>
        /// Save or update an entity to database.
        /// </summary>
        /// <param name="inst">
        /// The entity will be saved/updated.
        /// </param>
        void SaveOrUpdate(TE inst);

        /// <summary>
        /// Save or update a list of entities.
        /// </summary>
        /// <param name="instList">
        /// The entity list.
        /// </param>
        void SaveOrUpdate(ICollection<TE> instList);

        /// <summary>
        /// Find a list of matched entities by providing an hql and its parameters.
        /// </summary>
        /// <param name="query">
        /// The hql query.
        /// </param>
        /// <param name="paras">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<TE> Find(string query, params object[] paras);

        /// <summary>
        /// Find a list of matched entities by providing a LINQ query 
        /// delegate and its parameters.
        /// </summary>
        /// <param name="linqQuery">
        /// The <see cref="LinqQuery{T,TRet}"/> delegate
        /// </param>
        /// <param name="paras">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<TE> Find(LinqQuery<TE, TE> linqQuery, params object[] paras);

        /// <summary>
        /// Find a list of matched entities by providing an hql and its named parameters
        /// values from a value object.
        /// </summary>
        /// <param name="query">
        /// The hql query.
        /// </param>
        /// <param name="valObj">
        /// The value object for named parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<TE> FindByValObj(string query, object valObj);

        /// <summary>
        /// Find a list of entities by provide a named HQL and its parameters.
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="paras">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<TE> FindByNamedQuery(string queryName, params object[] paras);

        /// <summary>
        /// Find a list of entities by provide a named HQL and 
        /// parameter values from a value object
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="valObj">
        /// The value object for named parameters.
        /// </param>
        /// <returns>
        /// The matched entities.
        /// </returns>
        IList<TE> FindByNamedQueryAndValObj(string queryName, object valObj);

        /// <summary>
        /// Find the first matched entity by providing an HQL and its parameters.
        /// </summary>
        /// <param name="query">
        /// The HQL query.
        /// </param>
        /// <param name="paras">
        /// The query parameters.
        /// </param>
        /// <returns>
        /// The matched entity or null if not found.
        /// </returns>
        TE FindOne(string query, params object[] paras);

        /// <summary>
        /// Find the first matched entity by providing an HQL and 
        /// parameter values from a value object
        /// </summary>
        /// <param name="query">
        /// The HQL query.
        /// </param>
        /// <param name="valObj">
        /// The value object for named parameters.
        /// </param>
        /// <returns>
        /// The matched entity or null if not found.
        /// </returns>
        TE FindOneByValObj(string query, object valObj);

        /// <summary>
        /// Find the first matched entity by providing a named HQL and 
        /// parameter values from a value object
        /// </summary>
        /// <param name="queryName">
        /// The HQL query name.
        /// </param>
        /// <param name="valObj">
        /// The value object for named parameters.
        /// </param>
        /// <returns>
        /// The matched entity or null if not found.
        /// </returns>
        TE FindOneByNamedQueryAndValObj(string queryName, object valObj);

        /// <summary>
        /// Get number of matched entities by providing an HQL query and 
        /// its parameter values.
        /// </summary>
        /// <param name="query">
        /// The HQL query.
        /// </param>
        /// <param name="paras">
        /// The query parameter values.
        /// </param>
        /// <returns>
        /// The number of matched entities.
        /// </returns>
        int GetCount(string query, params object[] paras);

        /// <summary>
        /// Get number of matched entities by providing an HQL query and 
        /// parameter values from a value object.
        /// </summary>
        /// <param name="query">
        /// The HQL query.
        /// </param>
        /// <param name="valObj">
        /// The value object for named parameters.
        /// </param>
        /// <returns>
        /// The number of matched entities.
        /// </returns>
        int GetCountByValObj(string query, object valObj);

        /// <summary>
        /// Delete an entity.
        /// </summary>
        /// <param name="entity">
        /// The entity to delete.
        /// </param>
        void Delete(TE entity);

        /// <summary>
        /// Delete a list of entity.
        /// </summary>
        /// <param name="entities">
        /// The entities to delete.
        /// </param>
        void DeleteAll(IList<TE> entities);

        /// <summary>
        /// Delete the entity by its key
        /// </summary>
        /// <param name="key">
        /// The entity key.
        /// </param>
        /// <returns>
        /// Number of affected entity ussual 
        /// </returns>
        int DeleteByKey(TK key);

        /// <summary>
        /// Delete entities by their keys
        /// </summary>
        /// <param name="keys">
        /// The entity keys
        /// </param>
        void DeleteByKeys(IList<TK> keys);

        /// <summary>
        /// Batch update entities by providing an HQL query and 
        /// its paramenter values
        /// </summary>
        /// <param name="query">
        /// The HQL query
        /// </param>
        /// <param name="paras">
        /// The query parameters
        /// </param>
        /// <returns>
        /// Number of affected entities
        /// </returns>
        int BatchUpdate(string query, params object[] paras);

        /// <summary>
        /// Batch update entities by providing an HQL query and 
        /// parameter values from a value object.
        /// </summary>
        /// <param name="query">
        /// The HQL query.
        /// </param>
        /// <param name="valObj">
        /// The value object for named parameters.
        /// </param>
        /// <returns>
        /// Number of affected entities.
        /// </returns>
        int BatchUpdateByValObj(string query, object valObj);

        /// <summary>
        /// Batch update entities by providing a named HQL query and
        /// its paramenter values
        /// </summary>
        /// <param name="queryName">
        /// The named HQL query
        /// </param>
        /// <param name="paras">
        /// The query parameters
        /// </param>
        /// <returns>
        /// Number of affected entities
        /// </returns>
        int BatchUpdateByNamedQuery(string queryName, params object[] paras);

        /// <summary>
        /// Batch update entities by providing a named HQL query and
        /// parameter values from a value object.
        /// </summary>
        /// <param name="queryName">
        /// The named HQL query
        /// </param>
        /// <param name="valObj">
        /// The value object for named parameters.
        /// </param>
        /// <returns>
        /// Number of affected entities
        /// </returns>
        int BatchUpdateByNamedQueryAndValObj(string queryName, object valObj);

        /// <summary>
        /// Truncate related table of the entity type, fallback to delete if 
        /// the entity is mapped to many tables
        /// </summary>
        /// <returns>
        /// Number of affected records
        /// </returns>
        int Truncate();
    }
}